package com.多用户通讯编程.QQ.Server.QQservice;

import com.多用户通讯编程.QQ.Common.Message;
import com.多用户通讯编程.QQ.Common.MessageType;
import com.多用户通讯编程.QQ.Common.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

public class QQServer {
    /// 服务端的连接
    private static ServerSocket serverSocket;
    /// 用来存放用户信息的集合；
    private static ConcurrentHashMap<String , User> ServerHashMap = new ConcurrentHashMap();

    public static ConcurrentHashMap<String, User> getServerHashMap() {
        return ServerHashMap;
    }

    /// 静态代码块，在类加载是就初始化集合；
    static {
        ServerHashMap.put("至尊宝",new User("至尊宝","1"));
        ServerHashMap.put("紫霞仙子",new User("紫霞仙子","1"));
        ServerHashMap.put("菩提老祖",new User("菩提老祖","1"));
        ServerHashMap.put("唐僧",new User("唐僧","1"));
        ServerHashMap.put("猪八戒",new User("猪八戒","1"));
    }

    /// 检查用户是否正确
    public static boolean checkUserIsCorrect(String UserId, String password){
        /// 通过id获取一个对象，如果为空就表明没有该对象，直接返回false；
        User user = ServerHashMap.get(UserId);
        if (user == null)
            return false;
        /// 如果存在用户，就对比密码；
        if (!password.equals(user.getPassword()))
            return false;
        /// 都正确返回true
        return true;
    }

    public static void main(String[] args) {
        new QQServer();
    }

    public QQServer() {

        try {
            /// 创建服务器监听端口
            System.out.println("服务器9999端口 等待 客户端连接");
            serverSocket = new ServerSocket(9999);
            /// 推送线程启动
            new ServerPushThread().start();
            /// 创建消息对象；两端之间传送
            Message message = new Message();

            while (true) {
                /// 一直监听9999端口，只要有连接就创建一个客户端对象；
                Socket socket = serverSocket.accept();
                /// 得到客户端链接过来的输入流；
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                /// 得到对客户端的输出流；
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.flush();
                /// 读取登录验证的User对象
                User user = (User) ois.readObject();
                System.out.println("ID = "+user.getUserId()+" password = "+user.getPassword()+"尝试连接");

                /// 如果验证成功，继续；
                if (checkUserIsCorrect(user.getUserId(),user.getPassword())) {
                    /// 如果用户密码正确，就去验证一下是否已经登陆过，查看线程中有没有key = id 的value；
                    if (ManageServerConnectClientThread.get(user.getUserId()) != null){
                        System.out.println("ID = "+user.getUserId()+" 用户已存在 , 连接失败");
                        /// 返回类型是 用户已经存在；并跳过当前循环；
                        message.setMesType(MessageType.MESSAGE_USER_ALREADY_EXISTS);
                        oos.writeObject(message);
                        oos.flush();
                        continue;
                    }
                    /// 如果用户之前未登录状态且密码正确；
                    System.out.println("ID = "+user.getUserId()+" 连接成功");
                    /// 将纤细类型设置成 成功 并返回结果；客户端读取到后就 可以跟服务器通讯了
                    message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
                    oos.writeObject(message);
                    oos.flush();
                    /// 创建一个线程对象，里面包含 socket，用户名，跟用户通讯的输入流，输出流；
                    ServerConnectClientThread serverConnectClientThread =
                            new ServerConnectClientThread(socket,user.getUserId() , ois , oos);
                    /// 启动通讯线程；
                    serverConnectClientThread.start();
                    /// 将线程保存到集合当中，便于通过ID获取线程对象，进而获取 socket，用户名，跟用户通讯的输入流，输出流；
                    ManageServerConnectClientThread.put(user.getUserId(),serverConnectClientThread);

                    /**
                     * 1.每次有用户登录时看看离线消息中是否有属于他的消息，如果有
                     * 2.拿到消息列表依次发送
                     * 3.没有就不管
                     */
                    Vector<Message> messageVector = ManageOfflineMessages.getMessages(user.getUserId());
                    /// 如果没人留言就不管；
                    if (messageVector != null){
                        /// 给专门发送离线留言的线程，将消息队列，接收方都给他；
                        new SendOfflineMessageThread(user.getUserId(), messageVector).start();
                        /// 从集合中删除，防止多次发送；
                        ManageOfflineMessages.remove(user.getUserId());
                    }

                } else {
                    /// 如果连接失败，就设置成 失败MESSAGE_LOGIN_FAIL ，返回
                    System.out.println("ID = "+user.getUserId()+" 尝试连接失败");
                    message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
                    oos.writeObject(message);
                }
                


            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }  finally {
            try {
                serverSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }




    }

}
